package com.payment.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alipay.v3.ApiException;
import com.alipay.v3.model.AlipayTradeQueryResponseModel;
import com.alipay.v3.model.GoodsDetail;
import com.aliyun.enums.AliyunTradeStatus;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.exception.payment.PaymentException;
import com.common.rabbitmq.producer.core.OrderProducer;
import com.payment.domain.dto.OrderPaymentDto;
import com.payment.domain.pojo.PaymentRecord;
import com.payment.domain.vo.ZfbCallbackVo;
import com.payment.enums.PaymentStatus;
import com.payment.mapper.PaymentRecordMapper;
import com.payment.service.IPaymentRecordService;
import com.payment.service.PaymentServiceFactory;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;

/**
 * <p>
 * 支付记录表 服务实现类
 * </p>
 *
 * @author 小杰大人
 * @since 2025-09-29
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PaymentRecordServiceImpl extends ServiceImpl<PaymentRecordMapper, PaymentRecord> implements IPaymentRecordService {
    private final OrderProducer orderProducer;
    private final PaymentServiceFactory paymentServiceFactory;

    @Override
    @Transactional
    public String initiatePayment(OrderPaymentDto orderPaymentDto) {
        GoodsDetail[] goodsDetails = new GoodsDetail[1];
        goodsDetails[0] = new GoodsDetail();
        goodsDetails[0].setGoodsId(orderPaymentDto.getCourseId().toString());
        goodsDetails[0].setGoodsName(orderPaymentDto.getCourseName());
        goodsDetails[0].setPrice(orderPaymentDto.getCurPrice().toString());
        goodsDetails[0].setQuantity(orderPaymentDto.getQuantity());
        String form = paymentServiceFactory.payment(orderPaymentDto.getOrderNo(), orderPaymentDto.getPayAmount(), orderPaymentDto.getSubject(),goodsDetails);
        if (StrUtil.isEmptyIfStr(form)){
            throw new PaymentException(PaymentException.PAYMENT_FAILED);
        }
        if (!this.exists(new LambdaQueryWrapper<PaymentRecord>().eq(PaymentRecord::getOrderNo, orderPaymentDto.getOrderNo()))){
            // 插入支付记录
            PaymentRecord paymentRecord = PaymentRecord.builder()
                    .orderId(orderPaymentDto.getId())
                    .orderNo(orderPaymentDto.getOrderNo())
                    .userId(orderPaymentDto.getUserId())
                    .paymentType(orderPaymentDto.getPaymentType())
                    .paymentAmount(orderPaymentDto.getPayAmount())
                    .paymentStatus(PaymentStatus.UNPAID.getCode())
                    .build();
            this.save(paymentRecord);
        }
        return form;
    }

    @Override
    @Transactional
    public void paymentCallback(HttpServletRequest request, HttpServletResponse response) throws IOException, ApiException {
        ZfbCallbackVo callbacked = paymentServiceFactory.callback(request, response);
        PaymentRecord paymentRecord = PaymentRecord.builder()
                .tradeNo(callbacked.getTradeNo())
                .buyerOpenId(callbacked.getBuyerOpenId())
                .paymentStatus(PaymentStatus.SUCCESS.getCode())
                .callbackTime(LocalDateTime.now())
                .build();
        this.update(paymentRecord, new LambdaQueryWrapper<PaymentRecord>()
                .eq(PaymentRecord::getOrderNo, callbacked.getOrderNo()));
        // 订单支付成功
        orderProducer.orderPaySuccess(callbacked.getOrderNo());
    }

    @Override
    public Boolean queryPaymentResult(String orderNo) {
        PaymentRecord paymentRecord = baseMapper.querySelectByOrderNo(orderNo);
        if (paymentRecord == null){
            throw new PaymentException(PaymentException.PAYMENT_NOT_EXIST);
        }
        AlipayTradeQueryResponseModel responseModel = paymentServiceFactory.queryTrade(paymentRecord.getOrderNo(), paymentRecord.getTradeNo());
        return responseModel == null ? null : AliyunTradeStatus.TRADE_SUCCESS.getStatus().equals(responseModel.getTradeStatus());
    }

    @Override
    @Transactional
    public Boolean cancel(String orderNo) {
        PaymentRecord paymentRecord = baseMapper.querySelectByOrderNo(orderNo);
        if (PaymentStatus.SUCCESS.getCode() == paymentRecord.getPaymentStatus()){
            log.debug("订单：{} 已经支付成功，无法关闭", orderNo);
            return false;
        }
        String trade_no = paymentServiceFactory.cancel(paymentRecord.getOrderNo(),paymentRecord.getTradeNo());
        if (StrUtil.isEmptyIfStr(trade_no)){
            log.error("订单：{} 关闭失败", orderNo);
            return false;
        }else {
            this.update().setSql("payment_status", PaymentStatus.FAIL.getCode()).setSql("trade_no", trade_no).eq("order_no", orderNo).update();
            return true;
        }
    }

    @Override
    public PaymentRecord querySelectByOrderNo(String orderNo) {
        return baseMapper.querySelectByOrderNo(orderNo);
    }

    @Override
    @Transactional
    public Boolean paymentSuccess(String orderNo) {
        PaymentRecord paymentRecord = querySelectByOrderNo(orderNo);
        if (paymentRecord == null){
            log.error("订单：{} 不存在", orderNo);
            return false;
        }
        if (PaymentStatus.SUCCESS.getCode() == paymentRecord.getPaymentStatus()){
            log.debug("订单：{} 已经支付成功", orderNo);
            return true;
        }
        paymentRecord.setPaymentStatus(PaymentStatus.SUCCESS.getCode());
        return this.updateById(paymentRecord);
    }
}
